home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / rzsz9107.zip / ZM.C < prev    next >
C/C++ Source or Header  |  1991-02-20  |  18KB  |  919 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    05-24-89  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    long rclhdr(hdr) recover position offset from header
  14.  * 
  15.  *
  16.  *    This version implements numerous enhancements including ZMODEM
  17.  *    Run Length Encoding and variable length headers.  These
  18.  *    features were not funded by the original Telenet development
  19.  *    contract.
  20.  * 
  21.  * This software may be freely used for non commercial and
  22.  * educational (didactic only) purposes.  This software may also
  23.  * be freely used to support file transfer operations to or from
  24.  * licensed Omen Technology products.  Any programs which use
  25.  * part or all of this software must be provided in source form
  26.  * with this notice intact except by written permission from Omen
  27.  * Technology Incorporated.
  28.  * 
  29.  * Use of this software for commercial or administrative purposes
  30.  * except when exclusively limited to interfacing Omen Technology
  31.  * products requires a per port license payment of $20.00 US per
  32.  * port (less in quantity).  Use of this code by inclusion,
  33.  * decompilation, reverse engineering or any other means
  34.  * constitutes agreement to these conditions and acceptance of
  35.  * liability to license the materials and payment of reasonable
  36.  * legal costs necessary to enforce this license agreement.
  37.  *
  38.  *
  39.  *        Omen Technology Inc        FAX: 503-621-3745
  40.  *        Post Office Box 4681
  41.  *        Portland OR 97208
  42.  *
  43.  *    This code is made available in the hope it will be useful,
  44.  *    BUT WITHOUT ANY WARRANTY OF ANY KIND OR LIABILITY FOR ANY
  45.  *    DAMAGES OF ANY KIND.
  46.  *
  47.  */
  48.  
  49. #ifndef CANFDX
  50. #include "zmodem.h"
  51. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  52. #endif
  53.  
  54. #ifndef UNSL
  55. #define UNSL
  56. #endif
  57.  
  58.  
  59. /* Globals used by ZMODEM functions */
  60. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame */
  61. int Rxtype;        /* Type of header received */
  62. int Rxhlen;        /* Length of header received */
  63. int Rxcount;        /* Count of data bytes received */
  64. char Rxhdr[ZMAXHLEN];    /* Received header */
  65. char Txhdr[ZMAXHLEN];    /* Transmitted header */
  66. long Rxpos;        /* Received file position */
  67. long Txpos;        /* Transmitted file position */
  68. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  69. int Crc32t;        /* Controls 32 bit CRC being sent */
  70.             /* 1 == CRC32,  2 == CRC32 + RLE */
  71. int Crc32r;        /* Indicates/controls 32 bit CRC being received */
  72.             /* 0 == CRC16,  1 == CRC32,  2 == CRC32 + RLE */
  73. int Usevhdrs;        /* Use variable length headers */
  74. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  75. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  76. char *Altcan;        /* Alternate canit string */
  77.  
  78. static lastsent;    /* Last char we sent */
  79. static Not8bit;        /* Seven bits seen on header */
  80.  
  81. static char *frametypes[] = {
  82.     "No Response to Error Correction Request",    /* -4 */
  83.     "No Carrier Detect",        /* -3 */
  84.     "TIMEOUT",        /* -2 */
  85.     "ERROR",        /* -1 */
  86. #define FTOFFSET 4
  87.     "ZRQINIT",
  88.     "ZRINIT",
  89.     "ZSINIT",
  90.     "ZACK",
  91.     "ZFILE",
  92.     "ZSKIP",
  93.     "ZNAK",
  94.     "ZABORT",
  95.     "ZFIN",
  96.     "ZRPOS",
  97.     "ZDATA",
  98.     "ZEOF",
  99.     "ZFERR",
  100.     "ZCRC",
  101.     "ZCHALLENGE",
  102.     "ZCOMPL",
  103.     "ZCAN",
  104.     "ZFREECNT",
  105.     "ZCOMMAND",
  106.     "ZSTDERR",
  107.     "xxxxx"
  108. #define FRTYPES 22    /* Total number of frame types in this array */
  109.             /*  not including psuedo negative entries */
  110. };
  111.  
  112. static char badcrc[] = "Bad CRC";
  113.  
  114. /* Send ZMODEM binary header hdr of type type */
  115. zsbhdr(len, type, hdr)
  116. register char *hdr;
  117. {
  118.     register int n;
  119.     register unsigned short crc;
  120.  
  121. #ifndef DSZ
  122.     vfile("zsbhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  123.       frametypes[type+FTOFFSET], rclhdr(hdr));
  124. #endif
  125.     if (type == ZDATA)
  126.         for (n = Znulls; --n >=0; )
  127.             xsendline(0);
  128.  
  129.     xsendline(ZPAD); xsendline(ZDLE);
  130.  
  131.     switch (Crc32t=Txfcs32) {
  132.     case 2:
  133.         zsbh32(len, hdr, type, Usevhdrs?ZVBINR32:ZBINR32);
  134.         flushmo();  break;
  135.     case 1:
  136.         zsbh32(len, hdr, type, Usevhdrs?ZVBIN32:ZBIN32);  break;
  137.     default:
  138.         if (Usevhdrs) {
  139.             xsendline(ZVBIN);
  140.             zsendline(len);
  141.         }
  142.         else
  143.             xsendline(ZBIN);
  144.         zsendline(type);
  145.         crc = updcrc(type, 0);
  146.  
  147.         for (n=len; --n >= 0; ++hdr) {
  148.             zsendline(*hdr);
  149.             crc = updcrc((0377& *hdr), crc);
  150.         }
  151.         crc = updcrc(0,updcrc(0,crc));
  152.         zsendline(crc>>8);
  153.         zsendline(crc);
  154.     }
  155.     if (type != ZDATA)
  156.         flushmo();
  157. }
  158.  
  159.  
  160. /* Send ZMODEM binary header hdr of type type */
  161. zsbh32(len, hdr, type, flavour)
  162. register char *hdr;
  163. {
  164.     register int n;
  165.     register UNSL long crc;
  166.  
  167.     xsendline(flavour); 
  168.     if (Usevhdrs) 
  169.         zsendline(len);
  170.     zsendline(type);
  171.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  172.  
  173.     for (n=len; --n >= 0; ++hdr) {
  174.         crc = UPDC32((0377 & *hdr), crc);
  175.         zsendline(*hdr);
  176.     }
  177.     crc = ~crc;
  178.     for (n=4; --n >= 0;) {
  179.         zsendline((int)crc);
  180.         crc >>= 8;
  181.     }
  182. }
  183.  
  184. /* Send ZMODEM HEX header hdr of type type */
  185. zshhdr(len, type, hdr)
  186. register char *hdr;
  187. {
  188.     register int n;
  189.     register unsigned short crc;
  190.  
  191. #ifndef DSZ
  192.     vfile("zshhdr: %c %d %s %lx", Usevhdrs?'v':'f', len,
  193.       frametypes[type+FTOFFSET], rclhdr(hdr));
  194. #endif
  195.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE);
  196.     if (Usevhdrs) {
  197.         sendline(ZVHEX);
  198.         zputhex(len);
  199.     }
  200.     else
  201.         sendline(ZHEX);
  202.     zputhex(type);
  203.     Crc32t = 0;
  204.  
  205.     crc = updcrc(type, 0);
  206.     for (n=len; --n >= 0; ++hdr) {
  207.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  208.     }
  209.     crc = updcrc(0,updcrc(0,crc));
  210.     zputhex(crc>>8); zputhex(crc);
  211.  
  212.     /* Make it printable on remote machine */
  213.     sendline(015); sendline(0212);
  214.     /*
  215.      * Uncork the remote in case a fake XOFF has stopped data flow
  216.      */
  217.     if (type != ZFIN && type != ZACK)
  218.         sendline(021);
  219.     flushmo();
  220. }
  221.  
  222. /*
  223.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  224.  */
  225. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  226. zsdata(buf, length, frameend)
  227. register char *buf;
  228. {
  229.     register unsigned short crc;
  230.  
  231. #ifndef DSZ
  232.     vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  233. #endif
  234.     switch (Crc32t) {
  235.     case 1:
  236.         zsda32(buf, length, frameend);  break;
  237.     case 2:
  238.         zsdar32(buf, length, frameend);  break;
  239.     default:
  240.         crc = 0;
  241.         for (;--length >= 0; ++buf) {
  242.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  243.         }
  244.         xsendline(ZDLE); xsendline(frameend);
  245.         crc = updcrc(frameend, crc);
  246.  
  247.         crc = updcrc(0,updcrc(0,crc));
  248.         zsendline(crc>>8); zsendline(crc);
  249.     }
  250.     if (frameend == ZCRCW)
  251.         xsendline(XON);
  252.     if (frameend != ZCRCG)
  253.         flushmo();
  254. }
  255.  
  256. zsda32(buf, length, frameend)
  257. register char *buf;
  258. {
  259.     register int c;
  260.     register UNSL long crc;
  261.  
  262.     crc = 0xFFFFFFFFL;
  263.     for (;--length >= 0; ++buf) {
  264.         c = *buf & 0377;
  265.         if (c & 0140)
  266.             xsendline(lastsent = c);
  267.         else
  268.             zsendline(c);
  269.         crc = UPDC32(c, crc);
  270.     }
  271.     xsendline(ZDLE); xsendline(frameend);
  272.     crc = UPDC32(frameend, crc);
  273.  
  274.     crc = ~crc;
  275.     for (c=4; --c >= 0;) {
  276.         zsendline((int)crc);  crc >>= 8;
  277.     }
  278. }
  279.  
  280. /*
  281.  * Receive array buf of max length with ending ZDLE sequence
  282.  *  and CRC.  Returns the ending character or error code.
  283.  *  NB: On errors may store length+1 bytes!
  284.  */
  285. zrdata(buf, length)
  286. register char *buf;
  287. {
  288.     register int c;
  289.     register unsigned short crc;
  290.     register char *end;
  291.     register int d;
  292.  
  293.     switch (Crc32r) {
  294.     case 1:
  295.         return zrdat32(buf, length);
  296.     case 2:
  297.         return zrdatr32(buf, length);
  298.     }
  299.  
  300.     crc = Rxcount = 0;  end = buf + length;
  301.     while (buf <= end) {
  302.         if ((c = zdlread()) & ~0377) {
  303. crcfoo:
  304.             switch (c) {
  305.             case GOTCRCE:
  306.             case GOTCRCG:
  307.             case GOTCRCQ:
  308.             case GOTCRCW:
  309.                 crc = updcrc((d=c)&0377, crc);
  310.                 if ((c = zdlread()) & ~0377)
  311.                     goto crcfoo;
  312.                 crc = updcrc(c, crc);
  313.                 if ((c = zdlread()) & ~0377)
  314.                     goto crcfoo;
  315.                 crc = updcrc(c, crc);
  316.                 if (crc & 0xFFFF) {
  317.                     zperr(badcrc);
  318.                     return ERROR;
  319.                 }
  320.                 Rxcount = length - (end - buf);
  321. #ifndef DSZ
  322.                 vfile("zrdata: %d  %s", Rxcount,
  323.                  Zendnames[d-GOTCRCE&3]);
  324. #endif
  325.                 return d;
  326.             case GOTCAN:
  327.                 zperr("Sender Canceled");
  328.                 return ZCAN;
  329.             case TIMEOUT:
  330.                 zperr("TIMEOUT");
  331.                 return c;
  332.             default:
  333.                 garbitch(); return c;
  334.             }
  335.         }
  336.         *buf++ = c;
  337.         crc = updcrc(c, crc);
  338.     }
  339. #ifdef DSZ
  340.     garbitch(); 
  341. #else
  342.     zperr("Data subpacket too long");
  343. #endif
  344.     return ERROR;
  345. }
  346.  
  347. zrdat32(buf, length)
  348. register char *buf;
  349. {
  350.     register int c;
  351.     register UNSL long crc;
  352.     register char *end;
  353.     register int d;
  354.  
  355.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  356.     while (buf <= end) {
  357.         if ((c = zdlread()) & ~0377) {
  358. crcfoo:
  359.             switch (c) {
  360.             case GOTCRCE:
  361.             case GOTCRCG:
  362.             case GOTCRCQ:
  363.             case GOTCRCW:
  364.                 d = c;  c &= 0377;
  365.                 crc = UPDC32(c, crc);
  366.                 if ((c = zdlread()) & ~0377)
  367.                     goto crcfoo;
  368.                 crc = UPDC32(c, crc);
  369.                 if ((c = zdlread()) & ~0377)
  370.                     goto crcfoo;
  371.                 crc = UPDC32(c, crc);
  372.                 if ((c = zdlread()) & ~0377)
  373.                     goto crcfoo;
  374.                 crc = UPDC32(c, crc);
  375.                 if ((c = zdlread()) & ~0377)
  376.                     goto crcfoo;
  377.                 crc = UPDC32(c, crc);
  378.                 if (crc != 0xDEBB20E3) {
  379.                     zperr(badcrc);
  380.                     return ERROR;
  381.                 }
  382.                 Rxcount = length - (end - buf);
  383. #ifndef DSZ
  384.                 vfile("zrdat32: %d %s", Rxcount,
  385.                  Zendnames[d-GOTCRCE&3]);
  386. #endif
  387.                 return d;
  388.             case GOTCAN:
  389.                 zperr("Sender Canceled");
  390.                 return ZCAN;
  391.             case TIMEOUT:
  392.                 zperr("TIMEOUT");
  393.                 return c;
  394.             default:
  395.                 garbitch(); return c;
  396.             }
  397.         }
  398.         *buf++ = c;
  399.         crc = UPDC32(c, crc);
  400.     }
  401.     zperr("Data subpacket too long");
  402.     return ERROR;
  403. }
  404.  
  405. garbitch()
  406. {
  407.     zperr("Garbled data subpacket");
  408. }
  409.  
  410. /*
  411.  * Read a ZMODEM header to hdr, either binary or hex.
  412.  *  eflag controls local display of non zmodem characters:
  413.  *    0:  no display
  414.  *    1:  display printing characters only
  415.  *    2:  display all non ZMODEM characters
  416.  *
  417.  *   Set Rxhlen to size of header (default 4) (valid iff good hdr)
  418.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  419.  *   Otherwise return negative on error.
  420.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  421.  */
  422. zgethdr(hdr, eflag)
  423. char *hdr;
  424. {
  425.     register int c, n, cancount;
  426.  
  427.     n = Zrwindow + Effbaud;        /* Max bytes before start of frame */
  428.     Rxframeind = Rxtype = 0;
  429.  
  430. startover:
  431.     cancount = 5;
  432. again:
  433.     /* Return immediate ERROR if ZCRCW sequence seen */
  434.     switch (c = readline(Rxtimeout)) {
  435.     case 021: case 0221:
  436.         goto again;
  437.     case RCDO:
  438.     case TIMEOUT:
  439.         goto fifi;
  440.     case CAN:
  441. gotcan:
  442.         if (--cancount <= 0) {
  443.             c = ZCAN; goto fifi;
  444.         }
  445.         switch (c = readline(1)) {
  446.         case TIMEOUT:
  447.             goto again;
  448.         case ZCRCW:
  449.             switch (readline(1)) {
  450.             case TIMEOUT:
  451.                 c = ERROR; goto fifi;
  452.             case RCDO:
  453.                 goto fifi;
  454.             default:
  455.                 goto agn2;
  456.             }
  457.         case RCDO:
  458.             goto fifi;
  459.         default:
  460.             break;
  461.         case CAN:
  462.             if (--cancount <= 0) {
  463.                 c = ZCAN; goto fifi;
  464.             }
  465.             goto again;
  466.         }
  467.     /* **** FALL THRU TO **** */
  468.     default:
  469. agn2:
  470.         if ( --n == 0) {
  471.             c = GCOUNT;  goto fifi;
  472.         }
  473.         if (eflag && ((c &= 0177) & 0140))
  474.             bttyout(c);
  475.         else if (eflag > 1)
  476.             bttyout(c);
  477. #ifdef UNIX
  478.         fflush(stderr);
  479. #endif
  480.         goto startover;
  481.     case ZPAD|0200:        /* This is what we want. */
  482.         Not8bit = c;
  483.     case ZPAD:        /* This is what we want. */
  484.         break;
  485.     }
  486.     cancount = 5;
  487. splat:
  488.     switch (c = noxrd7()) {
  489.     case ZPAD:
  490.         goto splat;
  491.     case RCDO:
  492.     case TIMEOUT:
  493.         goto fifi;
  494.     default:
  495.         goto agn2;
  496.     case ZDLE:        /* This is what we want. */
  497.         break;
  498.     }
  499.  
  500.  
  501.     Rxhlen = 4;        /* Set default length */
  502.     Rxframeind = c = noxrd7();
  503.     switch (c) {
  504.     case ZVBIN32:
  505.         if ((Rxhlen = c = zdlread()) < 0)
  506.             goto fifi;
  507.         if (c > ZMAXHLEN)
  508.             goto agn2;
  509.         Crc32r = 1;  c = zrbhd32(hdr); break;
  510.     case ZBIN32:
  511.         if (Usevhdrs)
  512.             goto agn2;
  513.         Crc32r = 1;  c = zrbhd32(hdr); break;
  514.     case ZVBINR32:
  515.         if ((Rxhlen = c = zdlread()) < 0)
  516.             goto fifi;
  517.         if (c > ZMAXHLEN)
  518.             goto agn2;
  519.         Crc32r = 2;  c = zrbhd32(hdr); break;
  520.     case ZBINR32:
  521.         if (Usevhdrs)
  522.             goto agn2;
  523.         Crc32r = 2;  c = zrbhd32(hdr); break;
  524.     case RCDO:
  525.     case TIMEOUT:
  526.         goto fifi;
  527.     case ZVBIN:
  528.         if ((Rxhlen = c = zdlread()) < 0)
  529.             goto fifi;
  530.         if (c > ZMAXHLEN)
  531.             goto agn2;
  532.         Crc32r = 0;  c = zrbhdr(hdr); break;
  533.     case ZBIN:
  534.         if (Usevhdrs)
  535.             goto agn2;
  536.         Crc32r = 0;  c = zrbhdr(hdr); break;
  537.     case ZVHEX:
  538.         if ((Rxhlen = c = zgethex()) < 0)
  539.             goto fifi;
  540.         if (c > ZMAXHLEN)
  541.             goto agn2;
  542.         Crc32r = 0;  c = zrhhdr(hdr); break;
  543.     case ZHEX:
  544.         if (Usevhdrs)
  545.             goto agn2;
  546.         Crc32r = 0;  c = zrhhdr(hdr); break;
  547.     case CAN:
  548.         goto gotcan;
  549.     default:
  550.         goto agn2;
  551.     }
  552.     for (n = Rxhlen; ++n < ZMAXHLEN; )    /* Clear unused hdr bytes */
  553.         hdr[n] = 0;
  554.     Rxpos = hdr[ZP3] & 0377;
  555.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  556.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  557.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  558. fifi:
  559.     switch (c) {
  560.     case GOTCAN:
  561.         c = ZCAN;
  562.     /* **** FALL THRU TO **** */
  563.     case ZNAK:
  564.     case ZCAN:
  565.     case ERROR:
  566.     case TIMEOUT:
  567.     case RCDO:
  568.     case GCOUNT:
  569.         zperr("Got %s", frametypes[c+FTOFFSET]);
  570.     /* **** FALL THRU TO **** */
  571. #ifndef DSZ
  572.     default:
  573.         if (c >= -4 && c <= FRTYPES)
  574.             vfile("zgethdr: %c %d %s %lx", Rxframeind, Rxhlen,
  575.               frametypes[c+FTOFFSET], Rxpos);
  576.         else
  577.             vfile("zgethdr: %c %d %lx", Rxframeind, c, Rxpos);
  578. #endif
  579.     }
  580.     /* Use variable length headers if we got one */
  581.     if (c >= 0 && c <= FRTYPES && Rxframeind & 040)
  582.         Usevhdrs = 1;
  583.     return c;
  584. }
  585.  
  586. /* Receive a binary style header (type and position) */
  587. zrbhdr(hdr)
  588. register char *hdr;
  589. {
  590.     register int c, n;
  591.     register unsigned short crc;
  592.  
  593.     if ((c = zdlread()) & ~0377)
  594.         return c;
  595.     Rxtype = c;
  596.     crc = updcrc(c, 0);
  597.  
  598.     for (n=Rxhlen; --n >= 0; ++hdr) {
  599.         if ((c = zdlread()) & ~0377)
  600.             return c;
  601.         crc = updcrc(c, crc);
  602.         *hdr = c;
  603.     }
  604.     if ((c = zdlread()) & ~0377)
  605.         return c;
  606.     crc = updcrc(c, crc);
  607.     if ((c = zdlread()) & ~0377)
  608.         return c;
  609.     crc = updcrc(c, crc);
  610.     if (crc & 0xFFFF) {
  611.         zperr(badcrc);
  612.         return ERROR;
  613.     }
  614. #ifdef ZMODEM
  615.     Protocol = ZMODEM;
  616. #endif
  617.     Zmodem = 1;
  618.     return Rxtype;
  619. }
  620.  
  621. /* Receive a binary style header (type and position) with 32 bit FCS */
  622. zrbhd32(hdr)
  623. register char *hdr;
  624. {
  625.     register int c, n;
  626.     register UNSL long crc;
  627.  
  628.     if ((c = zdlread()) & ~0377)
  629.         return c;
  630.     Rxtype = c;
  631.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  632. #ifdef DEBUGZ
  633.     vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  634. #endif
  635.  
  636.     for (n=Rxhlen; --n >= 0; ++hdr) {
  637.         if ((c = zdlread()) & ~0377)
  638.             return c;
  639.         crc = UPDC32(c, crc);
  640.         *hdr = c;
  641. #ifdef DEBUGZ
  642.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  643. #endif
  644.     }
  645.     for (n=4; --n >= 0;) {
  646.         if ((c = zdlread()) & ~0377)
  647.             return c;
  648.         crc = UPDC32(c, crc);
  649. #ifdef DEBUGZ
  650.         vfile("zrbhd32 c=%X  crc=%lX", c, crc);
  651. #endif
  652.     }
  653.     if (crc != 0xDEBB20E3) {
  654.         zperr(badcrc);
  655.         return ERROR;
  656.     }
  657. #ifdef ZMODEM
  658.     Protocol = ZMODEM;
  659. #endif
  660.     Zmodem = 1;
  661.     return Rxtype;
  662. }
  663.  
  664.  
  665. /* Receive a hex style header (type and position) */
  666. zrhhdr(hdr)
  667. char *hdr;
  668. {
  669.     register int c;
  670.     register unsigned short crc;
  671.     register int n;
  672.  
  673.     if ((c = zgethex()) < 0)
  674.         return c;
  675.     Rxtype = c;
  676.     crc = updcrc(c, 0);
  677.  
  678.     for (n=Rxhlen; --n >= 0; ++hdr) {
  679.         if ((c = zgethex()) < 0)
  680.             return c;
  681.         crc = updcrc(c, crc);
  682.         *hdr = c;
  683.     }
  684.     if ((c = zgethex()) < 0)
  685.         return c;
  686.     crc = updcrc(c, crc);
  687.     if ((c = zgethex()) < 0)
  688.         return c;
  689.     crc = updcrc(c, crc);
  690.     if (crc & 0xFFFF) {
  691.         zperr(badcrc); return ERROR;
  692.     }
  693.     switch ( c = readline(2)) {
  694.     case 0215:
  695.         Not8bit = c;
  696.         /* **** FALL THRU TO **** */
  697.     case 015:
  698.          /* Throw away possible cr/lf */
  699.         switch (c = readline(2)) {
  700.         case 012:
  701.             Not8bit |= c;
  702.         }
  703.     }
  704. #ifdef ZMODEM
  705.     Protocol = ZMODEM;
  706. #endif
  707.     Zmodem = 1;
  708.     if (c < 0)
  709.         return c;
  710.     return Rxtype;
  711. }
  712.  
  713. /* Send a byte as two hex digits */
  714. zputhex(c)
  715. register int c;
  716. {
  717.     static char    digits[]    = "0123456789abcdef";
  718.  
  719. #ifdef DEBUGZ
  720.     if (Verbose>8)
  721.         vfile("zputhex: %02X", c);
  722. #endif
  723.     sendline(digits[(c&0xF0)>>4]);
  724.     sendline(digits[(c)&0xF]);
  725. }
  726.  
  727. /*
  728.  * Send character c with ZMODEM escape sequence encoding.
  729.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  730.  */
  731. zsendline(c)
  732. {
  733.  
  734.     /* Quick check for non control characters */
  735.     if (c & 0140)
  736.         xsendline(lastsent = c);
  737.     else {
  738.         switch (c &= 0377) {
  739.         case ZDLE:
  740.             xsendline(ZDLE);
  741.             xsendline (lastsent = (c ^= 0100));
  742.             break;
  743.         case 015:
  744.         case 0215:
  745.             if (!Zctlesc && (lastsent & 0177) != '@')
  746.                 goto sendit;
  747.         /* **** FALL THRU TO **** */
  748.         case 020:
  749.         case 021:
  750.         case 023:
  751.         case 0220:
  752.         case 0221:
  753.         case 0223:
  754.             xsendline(ZDLE);
  755.             c ^= 0100;
  756.     sendit:
  757.             xsendline(lastsent = c);
  758.             break;
  759.         default:
  760.             if (Zctlesc && ! (c & 0140)) {
  761.                 xsendline(ZDLE);
  762.                 c ^= 0100;
  763.             }
  764.             xsendline(lastsent = c);
  765.         }
  766.     }
  767. }
  768.  
  769. /* Decode two lower case hex digits into an 8 bit byte value */
  770. zgethex()
  771. {
  772.     register int c;
  773.  
  774.     c = zgeth1();
  775. #ifdef DEBUGZ
  776.     if (Verbose>8)
  777.         vfile("zgethex: %02X", c);
  778. #endif
  779.     return c;
  780. }
  781. zgeth1()
  782. {
  783.     register int c, n;
  784.  
  785.     if ((c = noxrd7()) < 0)
  786.         return c;
  787.     n = c - '0';
  788.     if (n > 9)
  789.         n -= ('a' - ':');
  790.     if (n & ~0xF)
  791.         return ERROR;
  792.     if ((c = noxrd7()) < 0)
  793.         return c;
  794.     c -= '0';
  795.     if (c > 9)
  796.         c -= ('a' - ':');
  797.     if (c & ~0xF)
  798.         return ERROR;
  799.     c += (n<<4);
  800.     return c;
  801. }
  802.  
  803. /*
  804.  * Read a byte, checking for ZMODEM escape encoding
  805.  *  including CAN*5 which represents a quick abort
  806.  */
  807. zdlread()
  808. {
  809.     register int c;
  810.  
  811. again:
  812.     /* Quick check for non control characters */
  813.     if ((c = readline(Rxtimeout)) & 0140)
  814.         return c;
  815.     switch (c) {
  816.     case ZDLE:
  817.         break;
  818.     case 023:
  819.     case 0223:
  820.     case 021:
  821.     case 0221:
  822.         goto again;
  823.     default:
  824.         if (Zctlesc && !(c & 0140)) {
  825.             goto again;
  826.         }
  827.         return c;
  828.     }
  829. again2:
  830.     if ((c = readline(Rxtimeout)) < 0)
  831.         return c;
  832.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  833.         return c;
  834.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  835.         return c;
  836.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  837.         return c;
  838.     switch (c) {
  839.     case CAN:
  840.         return GOTCAN;
  841.     case ZCRCE:
  842.     case ZCRCG:
  843.     case ZCRCQ:
  844.     case ZCRCW:
  845.         return (c | GOTOR);
  846.     case ZRUB0:
  847.         return 0177;
  848.     case ZRUB1:
  849.         return 0377;
  850.     case 023:
  851.     case 0223:
  852.     case 021:
  853.     case 0221:
  854.         goto again2;
  855.     default:
  856.         if (Zctlesc && ! (c & 0140)) {
  857.             goto again2;
  858.         }
  859.         if ((c & 0140) ==  0100)
  860.             return (c ^ 0100);
  861.         break;
  862.     }
  863.     if (Verbose>1)
  864.         zperr("Bad escape sequence %x", c);
  865.     return ERROR;
  866. }
  867.  
  868. /*
  869.  * Read a character from the modem line with timeout.
  870.  *  Eat parity, XON and XOFF characters.
  871.  */
  872. noxrd7()
  873. {
  874.     register int c;
  875.  
  876.     for (;;) {
  877.         if ((c = readline(Rxtimeout)) < 0)
  878.             return c;
  879.         switch (c &= 0177) {
  880.         case XON:
  881.         case XOFF:
  882.             continue;
  883.         default:
  884.             if (Zctlesc && !(c & 0140))
  885.                 continue;
  886.         case '\r':
  887.         case '\n':
  888.         case ZDLE:
  889.             return c;
  890.         }
  891.     }
  892. }
  893.  
  894. /* Store long integer pos in Txhdr */
  895. stohdr(pos)
  896. long pos;
  897. {
  898.     Txhdr[ZP0] = pos;
  899.     Txhdr[ZP1] = pos>>8;
  900.     Txhdr[ZP2] = pos>>16;
  901.     Txhdr[ZP3] = pos>>24;
  902. }
  903.  
  904. /* Recover a long integer from a header */
  905. long
  906. rclhdr(hdr)
  907. register char *hdr;
  908. {
  909.     register long l;
  910.  
  911.     l = (hdr[ZP3] & 0377);
  912.     l = (l << 8) | (hdr[ZP2] & 0377);
  913.     l = (l << 8) | (hdr[ZP1] & 0377);
  914.     l = (l << 8) | (hdr[ZP0] & 0377);
  915.     return l;
  916. }
  917.  
  918. /* End of zm.c */
  919.